package com.mrtrying.widget;

import android.content.Context;
import android.database.DataSetObservable;
import android.database.DataSetObserver;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Adapter;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

/**
 * Description :
 * PackageName : acore.widget
 * Created by mrtrying on 2019/2/28 14:26.
 * e_mail : ztanzeyu@gmail.com
 */
public class LabelsFlowLayout extends ViewGroup {

    public final static String TAG = "LabelsFlowLayout";

    /** 所有view，按行分 */
    protected List<List<View>> mAllViews = new ArrayList<>();
    /** 每行高度的位置 */
    protected List<Integer> mLineHeight = new ArrayList<>();
    /** 每行的每个view宽度位置 */
    protected List<List<Integer>> mLineViewWidth = new ArrayList<>();

    private LabelAdapter mLabelAdapter;

    public LabelsFlowLayout(Context context) {
        super(context);
    }

    public LabelsFlowLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public LabelsFlowLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public void setAdapter(LabelAdapter adapter) {
        this.mLabelAdapter = adapter;
        changeAdapter();
    }

    private void changeAdapter() {
        removeAllViews();
        for (int i = 0; i < mLabelAdapter.getCount(); i++) {
            View child = mLabelAdapter.getView(i, null, this);
            MarginLayoutParams lp = (MarginLayoutParams) (child.getLayoutParams() == null ? generateDefaultLayoutParams() : child.getLayoutParams());
            child.setLayoutParams(lp);
            addView(child);
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //获取测量layout宽高
        final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        //计算内容宽
        final int contentWidth = widthSize - getPaddingLeft() - getPaddingRight();
        //获取测量模式
        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);

        int width = 0, height = 0;
        int lineWidth = 0, lineHeight = 0;

        final int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            View child = getChildAt(i);
            if(child.getVisibility() == GONE){
                continue;
            }
            measureChild(child, widthMeasureSpec, heightMeasureSpec);
            MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
            //计算child宽高
            final int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
            final int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
            //不换行
            if (lineWidth + childWidth > contentWidth) {
                //换行
                width = Math.max(width, lineWidth);
                lineWidth = 0;

                height += lineHeight;
                lineHeight = childHeight;
            }

            lineWidth += childWidth;
            lineHeight = Math.max(childHeight, lineHeight);
        }

        width = Math.max(lineWidth, width);
        height += lineHeight;

        setMeasuredDimension(widthMode == MeasureSpec.EXACTLY ? widthSize : width + getPaddingLeft() + getPaddingRight(),
                heightMode == MeasureSpec.EXACTLY ? heightSize : height + getPaddingTop() + getPaddingBottom());

    }


    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        List<View> lineViews = new ArrayList<>();
        List<Integer> lineViewWidth = new ArrayList<>();
        mAllViews.clear();
        mLineHeight.clear();

        final int contentWidth = getWidth() - getPaddingLeft() - getPaddingRight();

        int lineWidth = 0, lineHeight = 0;
        int totalHeight = getPaddingTop();

        final int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            View child = getChildAt(i);
            if (child.getVisibility() == GONE) {
                lineViewWidth.add(lineWidth);
                continue;
            }

            MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
            int childWidth = child.getMeasuredWidth();
            int childHeight = child.getMeasuredHeight();

            //换行
            if (childWidth + lp.leftMargin + lp.rightMargin + lineWidth > contentWidth) {
                lineWidth = 0;

                lineHeight = childHeight + lp.topMargin + lp.bottomMargin;
                totalHeight += lineHeight;
                mLineHeight.add(totalHeight);

                mLineViewWidth.add(lineViewWidth);
                lineViewWidth = new ArrayList<>();

                mAllViews.add(lineViews);
                lineViews = new ArrayList<>();
            }

            lineWidth += childWidth + lp.leftMargin + lp.rightMargin;
            lineViewWidth.add(lineWidth);
            lineHeight = Math.max(lineHeight, childHeight + lp.topMargin + lp.bottomMargin);
            lineViews.add(child);
        }

        mLineViewWidth.add(lineViewWidth);
        totalHeight += lineHeight;
        mLineHeight.add(totalHeight);
        mAllViews.add(lineViews);

        int left = getPaddingLeft();
        int top = getPaddingTop();
        final int lineNum = mAllViews.size();
        for (int i = 0; i < lineNum; i++) {
            lineViews = mAllViews.get(i);

            for (int j = 0; j < lineViews.size(); j++) {
                View child = lineViews.get(j);
                if (child.getVisibility() == View.GONE) continue;

                MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();

                int lc = left + lp.leftMargin;
                int tc = top + lp.topMargin;
                int rc = lc + child.getMeasuredWidth();
                int bc = tc + child.getMeasuredHeight();

                child.layout(lc, tc, rc, bc);

                left += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
            }

            left = getPaddingLeft();
            top = mLineHeight.get(i);
        }

    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                findChildViewByXY(event.getX(),event.getY());
                break;
        }
        return super.onTouchEvent(event);
    }

    private int findChildViewByXY(float x, float y) {
        Log.i(TAG, "findChildViewByXY: x=" + x + ",y=" + y);
        int lines = mLineHeight.size();
        final int top = getPaddingTop();
        final int left = getPaddingLeft();
        int childIndex = -1;
        if(y<=top || x <= left){
            return childIndex;
        }
        for (int i = 0; i < lines; i++) {
            final int lineHeight = mLineHeight.get(i);
            List<Integer> lineViewWidth = mLineViewWidth.get(i);
            if (y <= lineHeight) {
                for (int j = 0; j < lineViewWidth.size(); j++) {
                    final int viewWidth = lineViewWidth.get(j);
                    if (x <= viewWidth) {
                        if(childIndex == -1 && j == 0){
                            childIndex = 0;
                        }else{
                            childIndex += j;
                        }
                        break;
                    }else if(j == lineViewWidth.size() - 1){
                        childIndex = -1;
                    }
                }
                if(childIndex != -1){
                    childIndex++;
                }
                break;
            } else {
                childIndex += lineViewWidth.size();
            }
        }
        //TODO
        if(childIndex >= 0 && childIndex < getChildCount()){
            TextView textView = (TextView) getChildAt(childIndex);
            Toast.makeText(getContext(), textView.getText(), Toast.LENGTH_SHORT).show();
        }
        Log.i(TAG, "findChildViewByXY: childIndex=" + childIndex);
        return childIndex;
    }

    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new MarginLayoutParams(getContext(), attrs);
    }

    @Override
    protected LayoutParams generateDefaultLayoutParams() {
        return new MarginLayoutParams(MarginLayoutParams.WRAP_CONTENT, MarginLayoutParams.WRAP_CONTENT);
    }

    @Override
    protected LayoutParams generateLayoutParams(LayoutParams p) {
        return new MarginLayoutParams(p);
    }

    public static abstract class LabelAdapter<T> implements Adapter {
        private final DataSetObservable mDataSetObservable = new DataSetObservable();
        private List<T> mData;

        public LabelAdapter(List<T> data) {
            mData = data;
        }

        @Override
        public int getCount() {
            return mData == null ? 0 : mData.size();
        }

        @Override
        public T getItem(int position) {
            return mData.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public void registerDataSetObserver(DataSetObserver observer) {
            mDataSetObservable.registerObserver(observer);
        }

        @Override
        public void unregisterDataSetObserver(DataSetObserver observer) {
            mDataSetObservable.unregisterObserver(observer);
        }

        @Override
        public boolean hasStableIds() {
            return false;
        }

        @Override
        public int getItemViewType(int position) {
            return 0;
        }

        @Override
        public int getViewTypeCount() {
            return 1;
        }

        @Override
        public boolean isEmpty() {
            return getCount() <= 0;
        }
    }
}
